﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VT.VI.MVC.Extensions.Compression.Resource;
using System.Reflection;

namespace VT.VI.MVC.Extensions.Compression.Configuration
{
    internal class MinifierFactory
    {
        internal static volatile Dictionary<ResourceType, Type> minifierCollection = new Dictionary<ResourceType, Type>();
        private static object locked = new object();

        static MinifierFactory()
        {
            LoadTypes();
        }

        /// <summary>
        /// Get an instance of the minifier type
        /// </summary>
        /// <param name="type">type to run</param>
        /// <returns>ICompress instance, null if not found</returns>
        internal static ICompress GetInstance(ResourceType type)
        {
            if (!minifierCollection.ContainsKey(type))
            {
                return null;
            }

            return (ICompress)Activator.CreateInstance(minifierCollection[type]);
        }

        /// <summary>
        /// Loads the all types from the configuration section
        /// </summary>
        internal static void LoadTypes()
        {

            CompositeResourceSection minifierconfig = CompositeResourceSection.Instance;

            if (minifierconfig == null || minifierconfig.MinifierList.Count == 0)
            {
                return;
            }

            string workingDir = AppDomain.CurrentDomain.BaseDirectory;

            foreach (Minifier min in minifierconfig.MinifierList)
            {
                string rtype = min.ResourceType;
                ResourceType resourceType = (ResourceType)Enum.Parse(typeof(ResourceType), rtype, true);

                //Assembly assemblyInstance = Assembly.Load(min.Assembly);

                Type minType = Type.GetType(min.Type);

                RegisterMinifier(resourceType, minType);
            }
        }

        /// <summary>
        /// Loads a minifier type in the cached collection
        /// </summary>
        /// <param name="resourceType">resource type</param>
        /// <param name="type">Type instance</param>
        /// <returns>true if registered, false if not</returns>
        internal static bool RegisterMinifier(ResourceType resourceType, Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException();
            }

            if (!type.IsClass)
            {
                throw new ArgumentException("The specified type must be a class.");
            }

            if (type.GetConstructor(Type.EmptyTypes) == null)
            {
                throw new ArgumentException("The specified type must have a parameter less constructor.");
            }

            if (type.IsInstanceOfType(typeof(ICompress)))
            {
                throw new ArgumentException("The specified type must implement ICompress.");
            }

            lock (locked)
            {
                if (minifierCollection.ContainsKey(resourceType))
                {
                    return false;
                }

                minifierCollection.Add(resourceType, type);
            }

            return true;
        }
    }
}
